﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dracham.Classes;
using System.IO;
using System.Collections;

namespace Dracham.Classes
{
    public class GameWorld
    {
        private static TimerCollection timers;
        private static Settings settings = new Settings(@"Settings.xml");

        private static List<Zone> zones = new List<Zone>();
        private static List<Account> accounts = new List<Account>();
        private static List<SpawnTimer> spawns = new List<SpawnTimer>();
        private static List<KeyValuePair<DrachamNetwork, String>> consoleClients = new List<KeyValuePair<DrachamNetwork, String>>();

        private static List<Spell> spellPool = new List<Spell>();
        private static List<Creature> creaturePool = new List<Creature>();
        private static List<Item> itemPool = new List<Item>();

        private static double goldRate;
        private static double experienceRate;

        public static DrachamDataContext DataContext { get; set; }

        public GameWorld()
        {
            try
            {
                GameWorld.DataContext = new DrachamDataContext(
                Dracham.Properties.Settings.Default.drachamConnectionString);
            }
            catch
            {
                Console.WriteLine("Unable to connect to the MSSQL-Server{0}Press any key to exit", Environment.NewLine);
                Console.Read();

                return;
            }

            GameWorld.goldRate = GameWorld.Settings.GetDouble("GoldRate");
            GameWorld.experienceRate = GameWorld.Settings.GetDouble("ExperienceRate");
            
            this.LoadObjects();

            GameWorld.timers = new TimerCollection();
            GameWorld.Timers.AddTimer(new WorldSave(TimeSpan.FromMinutes(
                GameWorld.Settings.GetInteger("AutoSaveRate")).TotalMilliseconds));

            this.LoadMaps();
            this.LoadQuests();
            this.LoadAccounts();
            this.LoadSpells();

            GameWorld.Zones.ForEach(delegate(Zone z)
            {
                PulseTimer pt = new PulseTimer(z);
                z.Pulser = pt;
            });
        }

        public static double GoldRate
        {
            get { return GameWorld.goldRate; }
            set { GameWorld.goldRate = value; }
        }

        public static double ExperienceRate
        {
            get { return GameWorld.experienceRate; }
            set { GameWorld.experienceRate = value; }
        }

        public static List<Zone> Zones
        {
            get { return zones; }
            set { zones = value; }
        }

        public static Settings Settings
        {
            get { return GameWorld.settings; }
            set { GameWorld.settings = value; }
        }

        public static List<Creature> CreaturePool
        {
            get { return creaturePool; }
            set { creaturePool = value; }
        }

        public static List<Spell> SpellPool
        {
            get { return GameWorld.spellPool; }
            set { GameWorld.spellPool = value; }
        }

        public static List<Account> Accounts
        {
            get { return accounts; }
            set { accounts = value; }
        }

        public static List<Item> ItemPool
        {
            get { return itemPool; }
            set { itemPool = value; }
        }

        public static TimerCollection Timers
        {
            get { return timers; }
            set { timers = value; }
        }

        public static List<SpawnTimer> Spawns
        {
            get { return spawns; }
            set { spawns = value; }
        }

        public static List<KeyValuePair<DrachamNetwork, String>> ConsoleClients
        {
            get { return GameWorld.consoleClients; }
            set { GameWorld.consoleClients = value; }
        }

        private void LoadObjects()
        {
            Console.Write(@"
                Loading items...         ");

            GameWorld.itemPool.AddRange(GameWorld.DataContext.Items.ToList());

            Console.Write(@"{0} Items loaded. Done.
                Loading creatures...         ", GameWorld.itemPool.Count);

            GameWorld.creaturePool.AddRange(GameWorld.DataContext.Creatures.ToList());

            Console.Write(@"{0} Creatures loaded. Done.", GameWorld.creaturePool.Count);
        }

        private void LoadMaps()
        {
            Console.Write(@"
                Loading maps...         ");
            
            FileInfo[] fi = new DirectoryInfo(@"Content\Maps").GetFiles("*.zdf");

            foreach (FileInfo f in fi)
            {
                Zone.LoadFromFile(f.FullName);
            }


            Console.Write(@"{0} Maps loaded. Done.", GameWorld.Zones.Count);
        }

        private void LoadQuests()
        {
            Console.Write(@"
                Loading quests...         ");

            Console.Write(@"{0} quests loaded. Done.", 0);
        }

        private void LoadAccounts()
        {
            Console.Write(@"
                Loading accounts...     ");

            foreach (Account acc in GameWorld.DataContext.Accounts)
            {
                accounts.Add(acc);
                foreach (Character c in acc.Characters)
                {
                    c.Initialize();
                }
            }

            Console.Write(@"{0} Accounts loaded. Done.", GameWorld.Accounts.Count);
        }

        private void LoadSpells()
        {
            Console.Write(@"
                Loading spells...     ");

            foreach (Spell spell in GameWorld.DataContext.Spells)
            {
                spellPool.Add(spell);
                spell.Initialize();
            }

            Console.Write(@"{0} Spells loaded. Done.", GameWorld.SpellPool.Count);
        }
    }

    public class WorldSave : GameTimer
    {
        public WorldSave(Double interval)
        {
            this.Interval = interval;
            this.LastRun = DateTime.Now;
        }

        public override void Run()
        {
            GameWorld.DataContext.SubmitChanges();
        }
    }
}
